Written by Steve Scherrer - July/August 2021

Background

This notebook documents preliminary analysis of tracking data for fish tagged in Molokini Crater between 2020-05-16 and 2021-05-24.

The purpose of this study is to understand how human impacts affect the fish of Molokini Crater

We are particularly interested in answering the following hypotheses: 1. Is the presence of fish affected by vessel presence

  1. Does the proportion of time fish are present within the crater negatively correlated with vessel presence?

Proposed Approach: 1. Begin by calculating the number of each species tagged and basic summary statistics 2. Calculate Metrics - Receiver Use - Pianka’s Niche Overlap - residency 3. Make the following plots - Map - Receiver locations - Map - Average receiver use by Species - Scatterplot - day night plots - Bar Plot - The number of detections per day (individual) - Bar Plot - The number of individuals detected (species) - Line Chart - The proportion of individuals detected n days after tagging (30 day moving average by species) - Bar Plot - Daily vessel traffic - Scatter Plot - vessel traffic vs. proportion of fish detected in crater daily (scatterplot by species) 4. Perform the following statistical Tests - Compare Residency Rates by Species - Compare residency by species, size, and time at liberty - Create a GLM comparing # of individuals in crater regressed against boat traffic and species using AR(1) term on dependent variable on some time scale (daily? 6 hours? depends on resolution of vessel data)

Workspace Setup

Establish Directory Heirarchy

project_directory = '/Users/stephenscherrer/Documents/Programming/Projects/Molokini'
scripts_directory = file.path(project_directory, 'Analysis Scripts')
data_directory = file.path(project_directory, 'Data')
results_directory = file.path(project_directory, 'Results')
figure_directory = file.path(results_directory, 'Figures')

Source package dependencies and utility functions from ‘Utility Functions.R’ file

source(file.path(scripts_directory, 'Utility Functions.R'))
Loading required package: suncalc
Registered S3 method overwritten by 'data.table':
  method           from
  print.data.table     
Loading required package: lubridate

Attaching package: ‘lubridate’

The following objects are masked from ‘package:base’:

    date, intersect, setdiff, union

Loading required package: readxl
Loading required package: ggplot2
RStudio Community is a great place to get help:
https://community.rstudio.com/c/tidyverse
Loading required package: data.table
data.table 1.13.0 using 1 threads (see ?getDTthreads).  Latest news: r-datatable.com
**********
This installation of data.table has not detected OpenMP support. It should still work but in single-threaded mode.
This is a Mac. Please read https://mac.r-project.org/openmp/. Please engage with Apple and ask them for support. Check r-datatable.com for updates, and our Mac instructions here: https://github.com/Rdatatable/data.table/wiki/Installation. After several years of many reports of installation problems on Mac, it's time to gingerly point out that there have been no similar problems on Windows or Linux.
**********

Attaching package: ‘data.table’

The following objects are masked from ‘package:lubridate’:

    hour, isoweek, mday, minute, month, quarter, second, wday, week,
    yday, year

Loading required package: reshape2

Attaching package: ‘reshape2’

The following objects are masked from ‘package:data.table’:

    dcast, melt

Loading required package: ggmap
Google's Terms of Service: https://cloud.google.com/maps-platform/terms/.
Please cite ggmap if you use it! See citation("ggmap") for details.
Loading required package: dplyr

Attaching package: ‘dplyr’

The following objects are masked from ‘package:data.table’:

    between, first, last

The following objects are masked from ‘package:stats’:

    filter, lag

The following objects are masked from ‘package:base’:

    intersect, setdiff, setequal, union

Load Data

  • load various datafiles
## Vessel Traffic data
vessel_df = load_vessel_data(file.path(data_directory, "Molokini_Master_June_21.csv"))
vessel_df$date
   [1] "1346493600" "1346752800" "1346925600" "1347098400" "1347357600"
   [6] "1347530400" "1347703200" "1347962400" "1348308000" "1348567200"
  [11] "1348740000" "1348826400" "1348912800" "1349172000" "1349517600"
  [16] "1349776800" "1349949600" "1350122400" "1350986400" "1351159200"
  [21] "1351591200" "1351764000" "1351936800" "1352196000" "1352368800"
  [26] "1352541600" "1353146400" "1353405600" "1353578400" "1353751200"
  [31] "1354183200" "1354356000" "1354701600" "1354960800" "1355047200"
  [36] "1355133600" "1355220000" "1355392800" "1355565600" "1356170400"
  [41] "1356429600" "1356602400" "1357207200" "1357380000" "1357639200"
  [46] "1357812000" "1358244000" "1358848800" "1359021600" "1359194400"
  [51] "1359453600" "1359626400" "1359799200" "1360058400" "1360231200"
  [56] "1360836000" "1361440800" "1361786400" "1361872800" "1362218400"
  [61] "1362477600" "1362650400" "1362823200" "1362909600" "1363082400"
  [66] "1363255200" "1363341600" "1363428000" "1363687200" "1363860000"
  [71] "1364032800" "1364292000" "1364464800" "1364637600" "1364896800"
  [76] "1365069600" "1365242400" "1365501600" "1365933600" "1366106400"
  [81] "1366279200" "1366711200" "1366884000" "1367316000" "1367920800"
  [86] "1368093600" "1368525600" "1368871200" "1369216800" "1369303200"
  [91] "1369735200" "1369908000" "1370080800" "1370340000" "1370426400"
  [96] "1370512800" "1370685600" "1370944800" "1371117600" "1371290400"
 [101] "1373364000" "1373968800" "1374141600" "1374314400" "1374573600"
 [106] "1374746400" "1374919200" "1375264800" "1375351200" "1375524000"
 [111] "1375783200" "1376128800" "1376388000" "1376560800" "1376733600"
 [116] "1376992800" "1377165600" "1377338400" "1377597600" "1377770400"
 [121] "1378202400" "1378375200" "1378548000" "1378807200" "1378980000"
 [126] "1379152800" "1379412000" "1379584800" "1380016800" "1380189600"
 [131] "1380621600" "1380967200" "1381226400" "1381399200" "1381572000"
 [136] "1381744800" "1381831200" "1382004000" "1382176800" "1382349600"
 [141] "1382436000" "1382608800" "1382781600" "1382954400" "1383040800"
 [146] "1383213600" "1383386400" "1383559200" "1383818400" "1383904800"
 [151] "1384250400" "1384423200" "1384596000" "1384768800" "1384855200"
 [156] "1384941600" "1385028000" "1385373600" "1385632800" "1385978400"
 [161] "1386064800" "1386237600" "1386410400" "1386583200" "1387188000"
 [166] "1387274400" "1387792800" "1389261600" "1389607200" "1389693600"
 [171] "1389866400" "1390039200" "1390557600" "1390816800" "1391076000"
 [176] "1392026400" "1392112800" "1392285600" "1392631200" "1392717600"
 [181] "1392804000" "1392890400" "1393668000" "1393927200" "1394100000"
 [186] "1394704800" "1395914400" "1396087200" "1396519200" "1396692000"
 [191] "1397124000" "1397728800" "1398074400" "1399111200" "1399197600"
 [196] "1399456800" "1399543200" "1399716000" "1400148000" "1400320800"
 [201] "1400407200" "1400580000" "1400752800" "1401357600" "1401789600"
 [206] "1401876000" "1401962400" "1402135200" "1402567200" "1402740000"
 [211] "1403172000" "1403344800" "1403604000" "1403776800" "1403949600"
 [216] "1404208800" "1404381600" "1405072800" "1405159200" "1405418400"
 [221] "1405504800" "1405591200" "1405677600" "1406023200" "1406196000"
 [226] "1406800800" "1406973600" "1407232800" "1407578400" "1408183200"
 [231] "1408442400" "1408788000" "1409047200" "1409479200" "1409565600"
 [236] "1410084000" "1410170400" "1410256800" "1410343200" "1410429600"
 [241] "1410775200" "1410861600" "1410948000" "1411034400" "1411207200"
 [246] "1411466400" "1411639200" "1411984800" "1412071200" "1412244000"
 [251] "1412416800" "1412416800" "1412589600" "1412676000" "1412848800"
 [256] "1413021600" "1413194400" "1413453600" "1413799200" "1413885600"
 [261] "1414058400" "1414404000" "1414490400" "1414836000" "1415008800"
 [266] "1415095200" "1415181600" "1415268000" "1415613600" "1415700000"
 [271] "1415872800" "1416045600" "1416477600" "1416650400" "1416823200"
 [276] "1417514400" "1417860000" "1418032800" "1418119200" "1418292000"
 [281] "1418637600" "1418896800" "1419501600" "1419674400" "1419933600"
 [286] "1420106400" "1420365600" "1420452000" "1420711200" "1421056800"
 [291] "1421143200" "1421661600" "1421748000" "1421920800" "1422352800"
 [296] "1422612000" "1423476000" "1423562400" "1424080800" "1424167200"
 [301] "1424340000" "1424685600" "1424772000" "1424944800" "1426154400"
 [306] "1426500000" "1426586400" "1426759200" "1427104800" "1427191200"
 [311] "1427709600" "1427968800" "1428141600" "1428400800" "1428919200"
 [316] "1429005600" "1429178400" "1429524000" "1429783200" "1430733600"
 [321] "1430820000" "1430906400" "1430992800" "1431252000" "1432548000"
 [326] "1432634400" "1432634400" "1432720800" "1432807200" "1433066400"
 [331] "1433239200" "1433325600" "1433412000" "1433844000" "1434016800"
 [336] "1434189600" "1434362400" "1434448800" "1434794400" "1434967200"
 [341] "1435053600" "1435226400" "1435572000" "1435658400" "1435831200"
 [346] "1436176800" "1436263200" "1436349600" "1436695200" "1436781600"
 [351] "1436868000" "1437040800" "1437300000" "1437472800" "1437645600"
 [356] "1438077600" "1438077600" "1438164000" "1438250400" "1438682400"
 [361] "1440496800" "1440583200" "1440669600" "1441101600" "1441188000"
 [366] "1441274400" "1441274400" "1441447200" "1441447200" "1441533600"
 [371] "1441620000" "1441706400" "1441706400" "1441879200" "1441879200"
 [376] "1442052000" "1442138400" "1442311200" "1442397600" "1442484000"
 [381] "1442656800" "1442743200" "1442829600" "1442916000" "1443088800"
 [386] "1443520800" "1445508000" "1445767200" "1445853600" "1446112800"
 [391] "1446372000" "1446458400" "1446544800" "1446717600" "1446976800"
 [396] "1447063200" "1447322400" "1447581600" "1447668000" "1447927200"
 [401] "1448186400" "1448272800" "1448791200" "1448877600" "1448964000"
 [406] "1449396000" "1449482400" "1450000800" "1450346400" "1450778400"
 [411] "1450951200" "1451210400" "1451728800" "1451815200" "1451988000"
 [416] "1452160800" "1452333600" "1452420000" "1452506400" "1452592800"
 [421] "1452765600" "1452938400" "1453111200" "1453197600" "1453543200"
 [426] "1453629600" "1453975200" "1454234400" "1454320800" "1454407200"
 [431] "1454580000" "1455012000" "1455184800" "1455444000" "1455616800"
 [436] "1455962400" "1456048800" "1456653600" "1456826400" "1456999200"
 [441] "1457258400" "1457344800" "1457863200" "1458468000" "1458554400"
 [446] "1458813600" "1458900000" "1459072800" "1459418400" "1459591200"
 [451] "1459677600" "1460196000" "1460368800" "1460628000" "1460887200"
 [456] "1461232800" "1461319200" "1461405600" "1461492000" "1461578400"
 [461] "1461837600" "1462096800" "1462183200" "1462269600" "1462356000"
 [466] "1462528800" "1462615200" "1462874400" "1463047200" "1463652000"
 [471] "1463911200" "1463997600" "1464084000" "1464256800" "1464343200"
 [476] "1464343200" "1464429600" "1464429600" "1464516000" "1464861600"
 [481] "1464861600" "1465034400" "1465120800" "1465466400" "1465639200"
 [486] "1465639200" "1465725600" "1466071200" "1466157600" "1466330400"
 [491] "1466416800" "1466503200" "1466589600" "1466676000" "1466935200"
 [496] "1467108000" "1467626400" "1467712800" "1467885600" "1468058400"
 [501] "1468144800" "1468231200" "1468317600" "1468663200" "1468749600"
 [506] "1468836000" "1468922400" "1469095200" "1469440800" "1469527200"
 [511] "1469700000" "1469872800" "1469959200" "1470045600" "1470132000"
 [516] "1470304800" "1470650400" "1470736800" "1471255200" "1471341600"
 [521] "1471514400" "1471773600" "1471860000" "1471946400" "1472119200"
 [526] "1472983200" "1473069600" "1473156000" "1473242400" "1473328800"
 [531] "1473501600" "1473588000" "1473674400" "1473760800" "1473847200"
 [536] "1473933600" "1474538400" "1474624800" "1474711200" "1474797600"
 [541] "1474884000" "1474970400" "1475143200" "1475316000" "1475402400"
 [546] "1475488800" "1475488800" "1475575200" "1475748000" "1476007200"
 [551] "1476093600" "1476352800" "1476612000" "1476784800" "1477216800"
 [556] "1477821600" "1477994400" "1478426400" "1478512800" "1478599200"
 [561] "1478599200" "1479117600" "1479204000" "1479376800" "1479376800"
 [566] "1479636000" "1479722400" "1479808800" "1480240800" "1480327200"
 [571] "1480413600" "1480845600" "1481450400" "1481623200" "1481968800"
 [576] "1482141600" "1482228000" "1482573600" "1482660000" "1482832800"
 [581] "1483437600" "1483524000" "1483610400" "1483869600" "1483956000"
 [586] "1484042400" "1484388000" "1484474400" "1484560800" "1484647200"
 [591] "1484820000" "1485165600" "1485252000" "1485511200" "1485597600"
 [596] "1485684000" "1486029600" "1486202400" "1486288800" "1486461600"
 [601] "1486634400" "1486980000" "1487066400" "1487412000" "1487671200"
 [606] "1487844000" "1488016800" "1488103200" "1488189600" "1488276000"
 [611] "1488448800" "1488535200" "1488967200" "1489053600" "1489226400"
 [616] "1489312800" "1489399200" "1489485600" "1489572000" "1489658400"
 [621] "1489744800" "1490090400" "1490176800" "1490263200" "1490436000"
 [626] "1490436000" "1490522400" "1490608800" "1490695200" "1490781600"
 [631] "1490868000" "1490954400" "1491040800" "1491127200" "1491213600"
 [636] "1491472800" "1491645600" "1491732000" "1491818400" "1491904800"
 [641] "1491991200" "1492077600" "1492250400" "1492423200" "1492509600"
 [646] "1492682400" "1492855200" "1495188000" "1495274400" "1495360800"
 [651] "1495447200" "1495533600" "1495620000" "1495706400" "1495879200"
 [656] "1495965600" "1496052000" "1496311200" "1496484000" "1496570400"
 [661] "1496656800" "1496743200" "1496829600" "1497002400" "1497088800"
 [666] "1497175200" "1497261600" "1497348000" "1497434400" "1497520800"
 [671] "1497607200" "1497693600" "1497780000" "1497866400" "1497952800"
 [676] "1498039200" "1498125600" "1498212000" "1498298400" "1498384800"
 [681] "1498471200" "1498557600" "1498730400" "1498903200" "1498989600"
 [686] "1499076000" "1499162400" "1499248800" "1499508000" "1499594400"
 [691] "1499680800" "1499767200" "1500112800" "1500199200" "1500285600"
 [696] "1500372000" "1500458400" "1500717600" "1500804000" "1500890400"
 [701] "1500976800" "1501063200" "1501668000" "1501927200" "1502100000"
 [706] "1502186400" "1502272800" "1502359200" "1502532000" "1502618400"
 [711] "1502704800" "1502791200" "1502877600" "1503136800" "1503223200"
 [716] "1503309600" "1503396000" "1503482400" "1503568800" "1503655200"
 [721] "1503914400" "1504000800" "1504087200" "1504260000" "1504346400"
 [726] "1504432800" "1504519200" "1504605600" "1504692000" "1504778400"
 [731] "1504951200" "1505037600" "1505124000" "1505210400" "1505296800"
 [736] "1505383200" "1505556000" "1505642400" "1505728800" "1505815200"
 [741] "1505901600" "1505988000" "1506160800" "1506420000" "1506506400"
 [746] "1506765600" "1506852000" "1506938400" "1507024800" "1507197600"
 [751] "1507370400" "1507456800" "1507543200" "1507629600" "1507716000"
 [756] "1507975200" "1508148000" "1508234400" "1508580000" "1508666400"
 [761] "1508752800" "1509184800" "1509271200" "1509357600" "1509444000"
 [766] "1509876000" "1510135200" "1510221600" "1510394400" "1510480800"
 [771] "1510567200" "1510999200" "1511258400" "1511690400" "1511863200"
 [776] "1512554400" "1512640800" "1512813600" "1512900000" "1512986400"
 [781] "1513072800" "1513504800" "1513591200" "1513677600" "1513764000"
 [786] "1514196000" "1514455200" "1514628000" "1514714400" "1514800800"
 [791] "1514887200"

Clean Data

  • Associate detections with time of day (day, night, dawn, dusk)
  • Remove detections from tags not associated with this study
  • Remove false detections
## Associate detections with time of day
molo_df = get_time_of_day(molo_df)

## Combine vue df with tagging df - remove irrelevant tags in the process
molo_df = inner_join(x = molo_df, y = tagging_df[ ,c('tag_id', 'species', 'fork_length', 'tagging_date' )], by = 'tag_id')

## Filter false detections
# molo_df = filter_false_detections(molo_df)

Exploratory Data Analysis

Count of individuals tagged by species

## Get count of individuals tagged by species
tags_by_species = aggregate(tag_id ~ species, data = tagging_df, FUN = uniqueN)
  colnames(tags_by_species) = c('species', 'tagged')
  
## Merge with count of individuals detected by species
tags_by_species = left_join(tags_by_species, aggregate(tag_id ~ species, data = molo_df, FUN = uniqueN), by = 'species')

## Replace NA values with 0
tags_by_species[is.na(tags_by_species)] = 0

print(tags_by_species)

Summary Statistics

# Time at liberty
time_at_liberty = calculate_time_at_liberty(molo_df)

# Days Detected
days_detected = calculate_days_detected(molo_df)

# % of days detected
detection_stats = merge(x = days_detected, y = time_at_liberty[ ,c('tag_id', 'days_at_liberty')], on.x = 'tag_id', on.y = 'tag_id')
detection_stats$percent_days_detected = round(detection_stats$unique_days / detection_stats$days_at_liberty, 4) * 100

# Merge with tagging data to get fish info
detection_stats = merge(x = tagging_df[ ,c('tagging_date', 'species', 'tag_id', 'fork_length')], y = detection_stats, on.x = 'tag_id', on.y = 'tag_id')
detection_stats = detection_stats[order(detection_stats$species, detection_stats$tagging_date, detection_stats$tag_id), ]
print(detection_stats)

Metric Calculations

index of receiver use

## sum all spp, sum all individuals (detections of tag at given reciever / all detections of tag)

## Calculate unique detections per tag per receiver station
detections_per_tag_per_receiver = aggregate(datetime~tag_id+receiver+species, data = molo_df, FUN = uniqueN)
colnames(detections_per_tag_per_receiver) = c('tag_id', 'receiver', 'species', 'detections')

## Calculate receiver use metric for each fish and receiver pair
detections_per_tag_per_receiver$receiver_use = 0
for (species in detections_per_tag_per_receiver$species){
  for (i in 1:nrow(detections_per_tag_per_receiver)){
    detections_per_tag_per_receiver$receiver_use[i] = detections_per_tag_per_receiver$detections[i] / sum(detections_per_tag_per_receiver$detections[detections_per_tag_per_receiver$tag_id == detections_per_tag_per_receiver$tag_id[i]])
  }
}

## Calculate average receiver use metric for each tag - Omit stations with no use as this would bias metric
indvidual_receiver_use = aggregate(receiver_use~tag_id+species, data = detections_per_tag_per_receiver[detections_per_tag_per_receiver$receiver_use > 0, ], FUN = mean)

## Add this information to detection_stats
detection_stats = merge(detection_stats, indvidual_receiver_use, on = 'tag_id')

## Calculate receiver use metric by species
species_receiver_use = aggregate(receiver_use~species, data = indvidual_receiver_use, FUN = mean)
colnames(species_receiver_use) = c('species', 'receiver_use')

print(species_receiver_use)

Calculate Pianka’s Niche Overlap Index - Pianka (1973) The Structure of Lizard Communities

0 = no overlap, 1 = perfect overlap

## Aggregate data averaged by species
receiver_use_aggregated_by_species = aggregate(receiver_use ~ species + receiver , data = detections_per_tag_per_receiver, FUN = mean)
  colnames(receiver_use_aggregated_by_species) = c('species', 'receiver', 'avg_use_index')
  
## Reshape from Long to Wide format
receiver_use_aggregated_by_species_wide = dcast(receiver_use_aggregated_by_species, species ~ receiver)
Using avg_use_index as value column: use value.var to override.
## Get all species combinations 
species_combos = data.frame()
for (i in 1:nrow(receiver_use_aggregated_by_species_wide)){
    if(i != nrow(receiver_use_aggregated_by_species_wide)){
    for (j in (i+1):nrow(receiver_use_aggregated_by_species_wide)){
      species_combos = rbind(species_combos, data.frame('species_1' = receiver_use_aggregated_by_species_wide$species[i], 'species_2' = receiver_use_aggregated_by_species_wide$species[j]))
    }
  }
}

## Change any NA values to zero
receiver_use_aggregated_by_species_wide[is.na(receiver_use_aggregated_by_species_wide)] = 0

## Calculate Pianka's index for all pairs
species_combos$pianka_index = 0
for(i in 1:nrow(species_combos)){
  species_combos$pianka_index[i] = sum(receiver_use_aggregated_by_species_wide[receiver_use_aggregated_by_species_wide$species == species_combos$species_1[i], -1] * 
     receiver_use_aggregated_by_species_wide[receiver_use_aggregated_by_species_wide$species == species_combos$species_2[i], -1]) /
    (sqrt(sum(receiver_use_aggregated_by_species_wide[receiver_use_aggregated_by_species_wide$species == species_combos$species_1[i], -1] ^ 2) * 
    sum(receiver_use_aggregated_by_species_wide[receiver_use_aggregated_by_species_wide$species == species_combos$species_2[i], -1] ^ 2)))
}

## Round to 3 digits
species_combos$pianka_index = round(species_combos$pianka_index, 3)

print(species_combos)

Plots

Study Area

## Plot study area and receivers
molo_basemap = get_map(location = c(lon = -156.496331, lat = 20.633007), zoom = 16, maptype = 'satellite')
Source : https://maps.googleapis.com/maps/api/staticmap?center=20.633007,-156.496331&zoom=16&size=640x640&scale=2&maptype=satellite&language=en-EN&key=xxx-hggZe5I57UhGHb8
receiver_map = ggmap(molo_basemap) + geom_point(data = molo_df, mapping = aes(x = lon, y = lat), col = 'red') + labs(x = '°Longitude', y = '°Latitude') + ggsave(filename = 'Receiver Locations Google Map.pdf', path = figure_directory)
Saving 7 x 7 in image
print(receiver_map)

Species Use Plots

## Get average use of receiver by species 
species_receiver_use = aggregate(receiver_use~species+receiver, data = detections_per_tag_per_receiver, FUN = mean)
  colnames(species_receiver_use) = c('species', 'receiver' , 'receiver_use')
  
## Merge with lat lon positions for each receiver from molo_df
receiver_postions =  unique(molo_df[ ,c('receiver', 'lat', 'lon')])
species_receiver_use = merge(x = species_receiver_use, y = receiver_postions, on = 'receiver', all.x = T, all.y = F)

## Make species plots for receiver use
for(species in species_receiver_use$species){
  receiver_use_by_spp = ggmap(molo_basemap) + 
    geom_point(data = species_receiver_use[species_receiver_use$species == species, ], 
               mapping = aes(x = lon, y = lat, color = 'red', size =  receiver_use)) + 
    labs(x = '°Longitude', y = '°Latitude') +
    ggsave(filename = paste('Receiver Use by ', species, '.pdf', sep = ''), path = figure_directory)
  print(receiver_use_by_spp)
}
Saving 7 x 7 in image

Day Night Plots

## By Individual
for (tag_id in unique(molo_df$tag_id)){
  print(tag_id)
    pdf(file = file.path(figure_directory, paste('Day Night Plot - Tag ID ', tag_id, '.pdf', sep = '')))
  plot_day_night(molo_df[molo_df$tag_id == tag_id, ], plot_title = paste(tagging_df$species[tagging_df$tag_id == tag_id], '- Tag', as.character(tag_id), sep = ' '))
  dev.off()
}
[1] "47513"
[1] "30711"
[1] "30754"
[1] "51591"
[1] "51590"
[1] "51593"
[1] "39194"
[1] "30755"
[1] "51594"

Barplot of detections by date

   ## Make and save plot
    ggplot(data = all_detections_long, mapping = aes(x = date, y = detections)) +
    geom_bar(stat = "identity") + 
    labs(title = 'All Tagged Individuals', x = 'Date', y = 'Detections') + 
    ggsave(filename = paste('Daily Detection Barplot - all tags.pdf'), path = figure_directory)
Saving 7 x 7 in image

Bar plot # of Fish (standardized percent of fish tagged to date) by date and Spp

THIS NEEDS WORK!!!

Bar plot vessel traffic by date

In the future, might also consider max vessels present at a given time

## Calculate Daily Vessel Stats
vessels_per_day = aggregate(vessel_name ~ Date(date), data = vessel_df, FUN = uniqueN)
Error in rep.int(NA_real_, length) : invalid 'times' value

Scatter plot x axis boat traffic, y axis presence / absence color by spp

Scatter plot x axis boat traffic, y axis detections per individual color by spp add error bars for daily detections

Residency and dispersal

## Calculate residency
detection_stats$residence_metric = detection_stats$unique_days / detection_stats$days_at_liberty

## Assign residence category: low = < 33%, medium = 33 - 66, high = >= 66 (Tinhan et al. 2014) -
detection_stats$residence_category = 'Low'
for (i in 1:nrow(detection_stats)){
  if (detection_stats$residence_metric[i] >= (1/3)) {
    detection_stats$residence_category[i] = 'Medium'
  }
  if (detection_stats$residence_metric[i] >= (2/3)) {
    detection_stats$residence_category[i] = 'High'
  }
}

## Create grouped barplot of residency by species
residence_counts_by_species = aggregate(tag_id ~ species + residence_category, data = detection_stats, FUN = length)

ggplot(data = residence_counts_by_species, mapping = aes(x=species, y=tag_id, fill=residence_category)) +
  geom_bar(stat="identity", position = "dodge")

Takeaways - All 4 omilus were highly resident as were grey reef sharks. No other species have replicates so…?

Calculate 30 day moving average of residency, then plot against days since tagging

Statistical analysis

Calculate mean residency by spp (irregardless of time), then ANOVA by spp Use Tukey’s HSD to determine significance

## ANOVA model for residency metric by species
residence_by_species_anova = aov(residence_metric ~ species, data=detection_stats)
summary(residence_by_species_anova)
            Df Sum Sq Mean Sq F value  Pr(>F)   
species      4 0.6781 0.16954   36.28 0.00212 **
Residuals    4 0.0187 0.00467                   
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
## Tukey's Honestly Significant Differences between species
TukeyHSD(residence_by_species_anova)
  Tukey multiple comparisons of means
    95% family-wise confidence level

Fit: aov(formula = residence_metric ~ species, data = detection_stats)

$species
                                           diff        lwr        upr
omilu-grey reef shark                0.13134256 -0.1318229  0.3945080
sandbar shark-grey reef shark       -0.78499266 -1.1571648 -0.4128205
ulua-grey reef shark                -0.04021073 -0.4123829  0.3319614
whitetip reef shark-grey reef shark  0.01604564 -0.3561265  0.3882178
sandbar shark-omilu                 -0.91633521 -1.2560803 -0.5765901
ulua-omilu                          -0.17155329 -0.5112984  0.1681918
whitetip reef shark-omilu           -0.11529692 -0.4550421  0.2244482
ulua-sandbar shark                   0.74478192  0.3150345  1.1745293
whitetip reef shark-sandbar shark    0.80103830  0.3712909  1.2307857
whitetip reef shark-ulua             0.05625637 -0.3734910  0.4860037
                                        p adj
omilu-grey reef shark               0.3282773
sandbar shark-grey reef shark       0.0034142
ulua-grey reef shark                0.9852738
whitetip reef shark-grey reef shark 0.9995567
sandbar shark-omilu                 0.0013197
ulua-omilu                          0.3205721
whitetip reef shark-omilu           0.6064486
ulua-sandbar shark                  0.0071653
whitetip reef shark-sandbar shark   0.0054544
whitetip reef shark-ulua            0.9710009

GLM comparing residency time by spp independent var (time at liberty) dependent (residency index)

summary(species_glm)

Call:
glm(formula = residence_metric ~ species, family = binomial(logit), 
    data = detection_stats)

Deviance Residuals: 
       1         2         3         4         5         6         7  
 0.00007   0.00007   0.00000  -0.26156   0.32896  -0.00022   0.00007  
       8         9  
 0.00000   0.00000  

Coefficients:
                           Estimate Std. Error z value Pr(>|z|)
(Intercept)                  1.8652     2.0751   0.899    0.369
speciesomilu                 4.0251     9.7553   0.413    0.680
speciessandbar shark        -4.2953     4.2135  -1.019    0.308
speciesulua                 -0.3098     3.3547  -0.092    0.926
specieswhitetip reef shark   0.1458     3.7297   0.039    0.969

(Dispersion parameter for binomial family taken to be 1)

    Null deviance: 4.31486  on 8  degrees of freedom
Residual deviance: 0.17663  on 4  degrees of freedom
AIC: 11.401

Number of Fisher Scoring iterations: 8

No Significant differences found

GLM comparing time in crater to vessel traffic

LS0tCnRpdGxlOiAiTW9sb2tpbmkgQW5hbHlzaXMiCm91dHB1dDogaHRtbF9ub3RlYm9vawotLS0KCiMgV3JpdHRlbiBieSBTdGV2ZSBTY2hlcnJlciAtIEp1bHkvQXVndXN0IDIwMjEKCiMjIEJhY2tncm91bmQKVGhpcyBub3RlYm9vayBkb2N1bWVudHMgcHJlbGltaW5hcnkgYW5hbHlzaXMgb2YgdHJhY2tpbmcgZGF0YSBmb3IgZmlzaCB0YWdnZWQgaW4gTW9sb2tpbmkgQ3JhdGVyIGJldHdlZW4gMjAyMC0wNS0xNiBhbmQgMjAyMS0wNS0yNC4gCgpUaGUgcHVycG9zZSBvZiB0aGlzIHN0dWR5IGlzIHRvIHVuZGVyc3RhbmQgaG93IGh1bWFuIGltcGFjdHMgYWZmZWN0IHRoZSBmaXNoIG9mIE1vbG9raW5pIENyYXRlcgoKV2UgYXJlIHBhcnRpY3VsYXJseSBpbnRlcmVzdGVkIGluIGFuc3dlcmluZyB0aGUgZm9sbG93aW5nIGh5cG90aGVzZXM6CjEuIElzIHRoZSBwcmVzZW5jZSBvZiBmaXNoIGFmZmVjdGVkIGJ5IHZlc3NlbCBwcmVzZW5jZQoKMi4gRG9lcyB0aGUgcHJvcG9ydGlvbiBvZiB0aW1lIGZpc2ggYXJlIHByZXNlbnQgd2l0aGluIHRoZSBjcmF0ZXIgbmVnYXRpdmVseSBjb3JyZWxhdGVkIHdpdGggdmVzc2VsIHByZXNlbmNlPwoKUHJvcG9zZWQgQXBwcm9hY2g6CjEuIEJlZ2luIGJ5IGNhbGN1bGF0aW5nIHRoZSBudW1iZXIgb2YgZWFjaCBzcGVjaWVzIHRhZ2dlZCBhbmQgYmFzaWMgc3VtbWFyeSBzdGF0aXN0aWNzCjIuIENhbGN1bGF0ZSBNZXRyaWNzCiAgLSBSZWNlaXZlciBVc2UKICAtIFBpYW5rYSdzIE5pY2hlIE92ZXJsYXAKICAtIHJlc2lkZW5jeQozLiBNYWtlIHRoZSBmb2xsb3dpbmcgcGxvdHMKICAtIE1hcCAtIFJlY2VpdmVyIGxvY2F0aW9ucwogIC0gTWFwIC0gQXZlcmFnZSByZWNlaXZlciB1c2UgYnkgU3BlY2llcwogIC0gU2NhdHRlcnBsb3QgLSBkYXkgbmlnaHQgcGxvdHMKICAtIEJhciBQbG90IC0gVGhlIG51bWJlciBvZiBkZXRlY3Rpb25zIHBlciBkYXkgKGluZGl2aWR1YWwpCiAgLSBCYXIgUGxvdCAtIFRoZSBudW1iZXIgb2YgaW5kaXZpZHVhbHMgZGV0ZWN0ZWQgKHNwZWNpZXMpCiAgLSBMaW5lIENoYXJ0IC0gVGhlIHByb3BvcnRpb24gb2YgaW5kaXZpZHVhbHMgZGV0ZWN0ZWQgbiBkYXlzIGFmdGVyIHRhZ2dpbmcgKDMwIGRheSBtb3ZpbmcgYXZlcmFnZSBieSBzcGVjaWVzKQogIC0gQmFyIFBsb3QgLSBEYWlseSB2ZXNzZWwgdHJhZmZpYwogIC0gU2NhdHRlciBQbG90IC0gdmVzc2VsIHRyYWZmaWMgdnMuIHByb3BvcnRpb24gb2YgZmlzaCBkZXRlY3RlZCBpbiBjcmF0ZXIgZGFpbHkgKHNjYXR0ZXJwbG90IGJ5IHNwZWNpZXMpCjQuIFBlcmZvcm0gdGhlIGZvbGxvd2luZyBzdGF0aXN0aWNhbCBUZXN0cwogIC0gQ29tcGFyZSBSZXNpZGVuY3kgUmF0ZXMgYnkgU3BlY2llcwogIC0gQ29tcGFyZSByZXNpZGVuY3kgYnkgc3BlY2llcywgc2l6ZSwgYW5kIHRpbWUgYXQgbGliZXJ0eQogIC0gQ3JlYXRlIGEgR0xNIGNvbXBhcmluZyAjIG9mIGluZGl2aWR1YWxzIGluIGNyYXRlciByZWdyZXNzZWQgYWdhaW5zdCBib2F0IHRyYWZmaWMgYW5kIHNwZWNpZXMgdXNpbmcgQVIoMSkgdGVybSBvbiBkZXBlbmRlbnQgdmFyaWFibGUgb24gc29tZSB0aW1lIHNjYWxlIChkYWlseT8gNiBob3Vycz8gZGVwZW5kcyBvbiByZXNvbHV0aW9uIG9mIHZlc3NlbCBkYXRhKQoKIyBXb3Jrc3BhY2UgU2V0dXAKIyMgRXN0YWJsaXNoIERpcmVjdG9yeSBIZWlyYXJjaHkKYGBge3J9CnByb2plY3RfZGlyZWN0b3J5ID0gJy9Vc2Vycy9zdGVwaGVuc2NoZXJyZXIvRG9jdW1lbnRzL1Byb2dyYW1taW5nL1Byb2plY3RzL01vbG9raW5pJwpzY3JpcHRzX2RpcmVjdG9yeSA9IGZpbGUucGF0aChwcm9qZWN0X2RpcmVjdG9yeSwgJ0FuYWx5c2lzIFNjcmlwdHMnKQpkYXRhX2RpcmVjdG9yeSA9IGZpbGUucGF0aChwcm9qZWN0X2RpcmVjdG9yeSwgJ0RhdGEnKQpyZXN1bHRzX2RpcmVjdG9yeSA9IGZpbGUucGF0aChwcm9qZWN0X2RpcmVjdG9yeSwgJ1Jlc3VsdHMnKQpmaWd1cmVfZGlyZWN0b3J5ID0gZmlsZS5wYXRoKHJlc3VsdHNfZGlyZWN0b3J5LCAnRmlndXJlcycpCmBgYAoKIyMgU291cmNlIHBhY2thZ2UgZGVwZW5kZW5jaWVzIGFuZCB1dGlsaXR5IGZ1bmN0aW9ucyBmcm9tICdVdGlsaXR5IEZ1bmN0aW9ucy5SJyBmaWxlCmBgYHtyfQpzb3VyY2UoZmlsZS5wYXRoKHNjcmlwdHNfZGlyZWN0b3J5LCAnVXRpbGl0eSBGdW5jdGlvbnMuUicpKQpgYGAKCiMjIExvYWQgRGF0YQotIGxvYWQgdmFyaW91cyBkYXRhZmlsZXMgCmBgYHtyfQojIyBGaWxlcyBmcm9tIFZVRSAKbW9sb19kZiA9IGxvYWRfdmVtY29fZGF0YShmaWxlLnBhdGgoZGF0YV9kaXJlY3RvcnksICdWVUVfRXhwb3J0LmNzdicpKQpmYWxzZV9kZXRlY3Rpb25zX2RmID0gbG9hZF9mZGZfcmVwb3J0KGZpbGUucGF0aChkYXRhX2RpcmVjdG9yeSwgJ0ZEQS5jc3YnKSkKCiMjIFZlc3NlbCBUcmFmZmljIGRhdGEKdmVzc2VsX2RmID0gbG9hZF92ZXNzZWxfZGF0YShmaWxlLnBhdGgoZGF0YV9kaXJlY3RvcnksICJNb2xva2luaV9NYXN0ZXJfSnVuZV8yMS5jc3YiKSkKCiMjIE1ldGFkYXRhIEZpbGVzCnRhZ2dpbmdfZGYgPSBsb2FkX3RhZ2dpbmdfZGF0YShmaWxlLnBhdGgoZGF0YV9kaXJlY3RvcnksICdNb2xva2luaV9GaXNoX1RhZ2dpbmdfbWFzdGVyLnhsc3gnKSkKCiMgcmVjZWl2ZXJfZGYgPSBsb2FkX3JlY2VpdmVyX2RhdGEoZmlsZS5wYXRoKGRhdGFfZGlyZWN0b3J5LCApKQpgYGAKCiMjIENsZWFuIERhdGEKLSBBc3NvY2lhdGUgZGV0ZWN0aW9ucyB3aXRoIHRpbWUgb2YgZGF5IChkYXksIG5pZ2h0LCBkYXduLCBkdXNrKQotIFJlbW92ZSBkZXRlY3Rpb25zIGZyb20gdGFncyBub3QgYXNzb2NpYXRlZCB3aXRoIHRoaXMgc3R1ZHkKLSBSZW1vdmUgZmFsc2UgZGV0ZWN0aW9ucwpgYGB7cn0KIyMgQXNzb2NpYXRlIGRldGVjdGlvbnMgd2l0aCB0aW1lIG9mIGRheQptb2xvX2RmID0gZ2V0X3RpbWVfb2ZfZGF5KG1vbG9fZGYpCgojIyBDb21iaW5lIHZ1ZSBkZiB3aXRoIHRhZ2dpbmcgZGYgLSByZW1vdmUgaXJyZWxldmFudCB0YWdzIGluIHRoZSBwcm9jZXNzCm1vbG9fZGYgPSBpbm5lcl9qb2luKHggPSBtb2xvX2RmLCB5ID0gdGFnZ2luZ19kZlsgLGMoJ3RhZ19pZCcsICdzcGVjaWVzJywgJ2ZvcmtfbGVuZ3RoJywgJ3RhZ2dpbmdfZGF0ZScgKV0sIGJ5ID0gJ3RhZ19pZCcpCgojIyBGaWx0ZXIgZmFsc2UgZGV0ZWN0aW9ucwojIG1vbG9fZGYgPSBmaWx0ZXJfZmFsc2VfZGV0ZWN0aW9ucyhtb2xvX2RmKQpgYGAKCiMgRXhwbG9yYXRvcnkgRGF0YSBBbmFseXNpcwojIyBDb3VudCBvZiBpbmRpdmlkdWFscyB0YWdnZWQgYnkgc3BlY2llcwpgYGB7cn0KIyMgR2V0IGNvdW50IG9mIGluZGl2aWR1YWxzIHRhZ2dlZCBieSBzcGVjaWVzCnRhZ3NfYnlfc3BlY2llcyA9IGFnZ3JlZ2F0ZSh0YWdfaWQgfiBzcGVjaWVzLCBkYXRhID0gdGFnZ2luZ19kZiwgRlVOID0gdW5pcXVlTikKICBjb2xuYW1lcyh0YWdzX2J5X3NwZWNpZXMpID0gYygnc3BlY2llcycsICd0YWdnZWQnKQogIAojIyBNZXJnZSB3aXRoIGNvdW50IG9mIGluZGl2aWR1YWxzIGRldGVjdGVkIGJ5IHNwZWNpZXMKdGFnc19ieV9zcGVjaWVzID0gbGVmdF9qb2luKHRhZ3NfYnlfc3BlY2llcywgYWdncmVnYXRlKHRhZ19pZCB+IHNwZWNpZXMsIGRhdGEgPSBtb2xvX2RmLCBGVU4gPSB1bmlxdWVOKSwgYnkgPSAnc3BlY2llcycpCgojIyBSZXBsYWNlIE5BIHZhbHVlcyB3aXRoIDAKdGFnc19ieV9zcGVjaWVzW2lzLm5hKHRhZ3NfYnlfc3BlY2llcyldID0gMAoKcHJpbnQodGFnc19ieV9zcGVjaWVzKQpgYGAKCiMjIFN1bW1hcnkgU3RhdGlzdGljcwpgYGB7cn0KIyBUaW1lIGF0IGxpYmVydHkKdGltZV9hdF9saWJlcnR5ID0gY2FsY3VsYXRlX3RpbWVfYXRfbGliZXJ0eShtb2xvX2RmKQoKIyBEYXlzIERldGVjdGVkCmRheXNfZGV0ZWN0ZWQgPSBjYWxjdWxhdGVfZGF5c19kZXRlY3RlZChtb2xvX2RmKQoKIyAlIG9mIGRheXMgZGV0ZWN0ZWQKZGV0ZWN0aW9uX3N0YXRzID0gbWVyZ2UoeCA9IGRheXNfZGV0ZWN0ZWQsIHkgPSB0aW1lX2F0X2xpYmVydHlbICxjKCd0YWdfaWQnLCAnZGF5c19hdF9saWJlcnR5JyldLCBvbi54ID0gJ3RhZ19pZCcsIG9uLnkgPSAndGFnX2lkJykKZGV0ZWN0aW9uX3N0YXRzJHBlcmNlbnRfZGF5c19kZXRlY3RlZCA9IHJvdW5kKGRldGVjdGlvbl9zdGF0cyR1bmlxdWVfZGF5cyAvIGRldGVjdGlvbl9zdGF0cyRkYXlzX2F0X2xpYmVydHksIDQpICogMTAwCgojIE1lcmdlIHdpdGggdGFnZ2luZyBkYXRhIHRvIGdldCBmaXNoIGluZm8KZGV0ZWN0aW9uX3N0YXRzID0gbWVyZ2UoeCA9IHRhZ2dpbmdfZGZbICxjKCd0YWdnaW5nX2RhdGUnLCAnc3BlY2llcycsICd0YWdfaWQnLCAnZm9ya19sZW5ndGgnKV0sIHkgPSBkZXRlY3Rpb25fc3RhdHMsIG9uLnggPSAndGFnX2lkJywgb24ueSA9ICd0YWdfaWQnKQpkZXRlY3Rpb25fc3RhdHMgPSBkZXRlY3Rpb25fc3RhdHNbb3JkZXIoZGV0ZWN0aW9uX3N0YXRzJHNwZWNpZXMsIGRldGVjdGlvbl9zdGF0cyR0YWdnaW5nX2RhdGUsIGRldGVjdGlvbl9zdGF0cyR0YWdfaWQpLCBdCnByaW50KGRldGVjdGlvbl9zdGF0cykKYGBgCgojIE1ldHJpYyBDYWxjdWxhdGlvbnMKIyMgaW5kZXggb2YgcmVjZWl2ZXIgdXNlCmBgYHtyfQojIyBzdW0gYWxsIHNwcCwgc3VtIGFsbCBpbmRpdmlkdWFscyAoZGV0ZWN0aW9ucyBvZiB0YWcgYXQgZ2l2ZW4gcmVjaWV2ZXIgLyBhbGwgZGV0ZWN0aW9ucyBvZiB0YWcpCgojIyBDYWxjdWxhdGUgdW5pcXVlIGRldGVjdGlvbnMgcGVyIHRhZyBwZXIgcmVjZWl2ZXIgc3RhdGlvbgpkZXRlY3Rpb25zX3Blcl90YWdfcGVyX3JlY2VpdmVyID0gYWdncmVnYXRlKGRhdGV0aW1lfnRhZ19pZCtyZWNlaXZlcitzcGVjaWVzLCBkYXRhID0gbW9sb19kZiwgRlVOID0gdW5pcXVlTikKY29sbmFtZXMoZGV0ZWN0aW9uc19wZXJfdGFnX3Blcl9yZWNlaXZlcikgPSBjKCd0YWdfaWQnLCAncmVjZWl2ZXInLCAnc3BlY2llcycsICdkZXRlY3Rpb25zJykKCiMjIENhbGN1bGF0ZSByZWNlaXZlciB1c2UgbWV0cmljIGZvciBlYWNoIGZpc2ggYW5kIHJlY2VpdmVyIHBhaXIKZGV0ZWN0aW9uc19wZXJfdGFnX3Blcl9yZWNlaXZlciRyZWNlaXZlcl91c2UgPSAwCmZvciAoc3BlY2llcyBpbiBkZXRlY3Rpb25zX3Blcl90YWdfcGVyX3JlY2VpdmVyJHNwZWNpZXMpewogIGZvciAoaSBpbiAxOm5yb3coZGV0ZWN0aW9uc19wZXJfdGFnX3Blcl9yZWNlaXZlcikpewogICAgZGV0ZWN0aW9uc19wZXJfdGFnX3Blcl9yZWNlaXZlciRyZWNlaXZlcl91c2VbaV0gPSBkZXRlY3Rpb25zX3Blcl90YWdfcGVyX3JlY2VpdmVyJGRldGVjdGlvbnNbaV0gLyBzdW0oZGV0ZWN0aW9uc19wZXJfdGFnX3Blcl9yZWNlaXZlciRkZXRlY3Rpb25zW2RldGVjdGlvbnNfcGVyX3RhZ19wZXJfcmVjZWl2ZXIkdGFnX2lkID09IGRldGVjdGlvbnNfcGVyX3RhZ19wZXJfcmVjZWl2ZXIkdGFnX2lkW2ldXSkKICB9Cn0KCiMjIENhbGN1bGF0ZSBhdmVyYWdlIHJlY2VpdmVyIHVzZSBtZXRyaWMgZm9yIGVhY2ggdGFnIC0gT21pdCBzdGF0aW9ucyB3aXRoIG5vIHVzZSBhcyB0aGlzIHdvdWxkIGJpYXMgbWV0cmljCmluZHZpZHVhbF9yZWNlaXZlcl91c2UgPSBhZ2dyZWdhdGUocmVjZWl2ZXJfdXNlfnRhZ19pZCtzcGVjaWVzLCBkYXRhID0gZGV0ZWN0aW9uc19wZXJfdGFnX3Blcl9yZWNlaXZlcltkZXRlY3Rpb25zX3Blcl90YWdfcGVyX3JlY2VpdmVyJHJlY2VpdmVyX3VzZSA+IDAsIF0sIEZVTiA9IG1lYW4pCgojIyBBZGQgdGhpcyBpbmZvcm1hdGlvbiB0byBkZXRlY3Rpb25fc3RhdHMKZGV0ZWN0aW9uX3N0YXRzID0gbWVyZ2UoZGV0ZWN0aW9uX3N0YXRzLCBpbmR2aWR1YWxfcmVjZWl2ZXJfdXNlLCBvbiA9ICd0YWdfaWQnKQoKIyMgQ2FsY3VsYXRlIHJlY2VpdmVyIHVzZSBtZXRyaWMgYnkgc3BlY2llcwpzcGVjaWVzX3JlY2VpdmVyX3VzZSA9IGFnZ3JlZ2F0ZShyZWNlaXZlcl91c2V+c3BlY2llcywgZGF0YSA9IGluZHZpZHVhbF9yZWNlaXZlcl91c2UsIEZVTiA9IG1lYW4pCmNvbG5hbWVzKHNwZWNpZXNfcmVjZWl2ZXJfdXNlKSA9IGMoJ3NwZWNpZXMnLCAncmVjZWl2ZXJfdXNlJykKCnByaW50KHNwZWNpZXNfcmVjZWl2ZXJfdXNlKQpgYGAgCiMjIENhbGN1bGF0ZSBQaWFua2EncyBOaWNoZSBPdmVybGFwIEluZGV4IC0gUGlhbmthICgxOTczKSBUaGUgU3RydWN0dXJlIG9mIExpemFyZCBDb21tdW5pdGllcwogMCA9IG5vIG92ZXJsYXAsIDEgPSBwZXJmZWN0IG92ZXJsYXAKYGBge3J9CiMjIEFnZ3JlZ2F0ZSBkYXRhIGF2ZXJhZ2VkIGJ5IHNwZWNpZXMKcmVjZWl2ZXJfdXNlX2FnZ3JlZ2F0ZWRfYnlfc3BlY2llcyA9IGFnZ3JlZ2F0ZShyZWNlaXZlcl91c2UgfiBzcGVjaWVzICsgcmVjZWl2ZXIgLCBkYXRhID0gZGV0ZWN0aW9uc19wZXJfdGFnX3Blcl9yZWNlaXZlciwgRlVOID0gbWVhbikKICBjb2xuYW1lcyhyZWNlaXZlcl91c2VfYWdncmVnYXRlZF9ieV9zcGVjaWVzKSA9IGMoJ3NwZWNpZXMnLCAncmVjZWl2ZXInLCAnYXZnX3VzZV9pbmRleCcpCiAgCiMjIFJlc2hhcGUgZnJvbSBMb25nIHRvIFdpZGUgZm9ybWF0CnJlY2VpdmVyX3VzZV9hZ2dyZWdhdGVkX2J5X3NwZWNpZXNfd2lkZSA9IGRjYXN0KHJlY2VpdmVyX3VzZV9hZ2dyZWdhdGVkX2J5X3NwZWNpZXMsIHNwZWNpZXMgfiByZWNlaXZlcikKCiMjIEdldCBhbGwgc3BlY2llcyBjb21iaW5hdGlvbnMgCnNwZWNpZXNfY29tYm9zID0gZGF0YS5mcmFtZSgpCmZvciAoaSBpbiAxOm5yb3cocmVjZWl2ZXJfdXNlX2FnZ3JlZ2F0ZWRfYnlfc3BlY2llc193aWRlKSl7CiAgICBpZihpICE9IG5yb3cocmVjZWl2ZXJfdXNlX2FnZ3JlZ2F0ZWRfYnlfc3BlY2llc193aWRlKSl7CiAgICBmb3IgKGogaW4gKGkrMSk6bnJvdyhyZWNlaXZlcl91c2VfYWdncmVnYXRlZF9ieV9zcGVjaWVzX3dpZGUpKXsKICAgICAgc3BlY2llc19jb21ib3MgPSByYmluZChzcGVjaWVzX2NvbWJvcywgZGF0YS5mcmFtZSgnc3BlY2llc18xJyA9IHJlY2VpdmVyX3VzZV9hZ2dyZWdhdGVkX2J5X3NwZWNpZXNfd2lkZSRzcGVjaWVzW2ldLCAnc3BlY2llc18yJyA9IHJlY2VpdmVyX3VzZV9hZ2dyZWdhdGVkX2J5X3NwZWNpZXNfd2lkZSRzcGVjaWVzW2pdKSkKICAgIH0KICB9Cn0KCiMjIENoYW5nZSBhbnkgTkEgdmFsdWVzIHRvIHplcm8KcmVjZWl2ZXJfdXNlX2FnZ3JlZ2F0ZWRfYnlfc3BlY2llc193aWRlW2lzLm5hKHJlY2VpdmVyX3VzZV9hZ2dyZWdhdGVkX2J5X3NwZWNpZXNfd2lkZSldID0gMAoKIyMgQ2FsY3VsYXRlIFBpYW5rYSdzIGluZGV4IGZvciBhbGwgcGFpcnMKc3BlY2llc19jb21ib3MkcGlhbmthX2luZGV4ID0gMApmb3IoaSBpbiAxOm5yb3coc3BlY2llc19jb21ib3MpKXsKICBzcGVjaWVzX2NvbWJvcyRwaWFua2FfaW5kZXhbaV0gPSBzdW0ocmVjZWl2ZXJfdXNlX2FnZ3JlZ2F0ZWRfYnlfc3BlY2llc193aWRlW3JlY2VpdmVyX3VzZV9hZ2dyZWdhdGVkX2J5X3NwZWNpZXNfd2lkZSRzcGVjaWVzID09IHNwZWNpZXNfY29tYm9zJHNwZWNpZXNfMVtpXSwgLTFdICogCiAgICAgcmVjZWl2ZXJfdXNlX2FnZ3JlZ2F0ZWRfYnlfc3BlY2llc193aWRlW3JlY2VpdmVyX3VzZV9hZ2dyZWdhdGVkX2J5X3NwZWNpZXNfd2lkZSRzcGVjaWVzID09IHNwZWNpZXNfY29tYm9zJHNwZWNpZXNfMltpXSwgLTFdKSAvCiAgICAoc3FydChzdW0ocmVjZWl2ZXJfdXNlX2FnZ3JlZ2F0ZWRfYnlfc3BlY2llc193aWRlW3JlY2VpdmVyX3VzZV9hZ2dyZWdhdGVkX2J5X3NwZWNpZXNfd2lkZSRzcGVjaWVzID09IHNwZWNpZXNfY29tYm9zJHNwZWNpZXNfMVtpXSwgLTFdIF4gMikgKiAKICAgIHN1bShyZWNlaXZlcl91c2VfYWdncmVnYXRlZF9ieV9zcGVjaWVzX3dpZGVbcmVjZWl2ZXJfdXNlX2FnZ3JlZ2F0ZWRfYnlfc3BlY2llc193aWRlJHNwZWNpZXMgPT0gc3BlY2llc19jb21ib3Mkc3BlY2llc18yW2ldLCAtMV0gXiAyKSkpCn0KCiMjIFJvdW5kIHRvIDMgZGlnaXRzCnNwZWNpZXNfY29tYm9zJHBpYW5rYV9pbmRleCA9IHJvdW5kKHNwZWNpZXNfY29tYm9zJHBpYW5rYV9pbmRleCwgMykKCnByaW50KHNwZWNpZXNfY29tYm9zKQpgYGAKCiMjIFBsb3RzClN0dWR5IEFyZWEKYGBge3J9CiMjIFBsb3Qgc3R1ZHkgYXJlYSBhbmQgcmVjZWl2ZXJzCm1vbG9fYmFzZW1hcCA9IGdldF9tYXAobG9jYXRpb24gPSBjKGxvbiA9IC0xNTYuNDk2MzMxLCBsYXQgPSAyMC42MzMwMDcpLCB6b29tID0gMTYsIG1hcHR5cGUgPSAnc2F0ZWxsaXRlJykKcmVjZWl2ZXJfbWFwID0gZ2dtYXAobW9sb19iYXNlbWFwKSArIGdlb21fcG9pbnQoZGF0YSA9IG1vbG9fZGYsIG1hcHBpbmcgPSBhZXMoeCA9IGxvbiwgeSA9IGxhdCksIGNvbCA9ICdyZWQnKSArIGxhYnMoeCA9ICfCsExvbmdpdHVkZScsIHkgPSAnwrBMYXRpdHVkZScpICsgZ2dzYXZlKGZpbGVuYW1lID0gJ1JlY2VpdmVyIExvY2F0aW9ucyBHb29nbGUgTWFwLnBkZicsIHBhdGggPSBmaWd1cmVfZGlyZWN0b3J5KQpwcmludChyZWNlaXZlcl9tYXApCmBgYAoKIyMjIFNwZWNpZXMgVXNlIFBsb3RzCmBgYHtyfQojIyBHZXQgYXZlcmFnZSB1c2Ugb2YgcmVjZWl2ZXIgYnkgc3BlY2llcyAKc3BlY2llc19yZWNlaXZlcl91c2UgPSBhZ2dyZWdhdGUocmVjZWl2ZXJfdXNlfnNwZWNpZXMrcmVjZWl2ZXIsIGRhdGEgPSBkZXRlY3Rpb25zX3Blcl90YWdfcGVyX3JlY2VpdmVyLCBGVU4gPSBtZWFuKQogIGNvbG5hbWVzKHNwZWNpZXNfcmVjZWl2ZXJfdXNlKSA9IGMoJ3NwZWNpZXMnLCAncmVjZWl2ZXInICwgJ3JlY2VpdmVyX3VzZScpCiAgCiMjIE1lcmdlIHdpdGggbGF0IGxvbiBwb3NpdGlvbnMgZm9yIGVhY2ggcmVjZWl2ZXIgZnJvbSBtb2xvX2RmCnJlY2VpdmVyX3Bvc3Rpb25zID0gIHVuaXF1ZShtb2xvX2RmWyAsYygncmVjZWl2ZXInLCAnbGF0JywgJ2xvbicpXSkKc3BlY2llc19yZWNlaXZlcl91c2UgPSBtZXJnZSh4ID0gc3BlY2llc19yZWNlaXZlcl91c2UsIHkgPSByZWNlaXZlcl9wb3N0aW9ucywgb24gPSAncmVjZWl2ZXInLCBhbGwueCA9IFQsIGFsbC55ID0gRikKCiMjIE1ha2Ugc3BlY2llcyBwbG90cyBmb3IgcmVjZWl2ZXIgdXNlCmZvcihzcGVjaWVzIGluIHNwZWNpZXNfcmVjZWl2ZXJfdXNlJHNwZWNpZXMpewogIHJlY2VpdmVyX3VzZV9ieV9zcHAgPSBnZ21hcChtb2xvX2Jhc2VtYXApICsgCiAgICBnZW9tX3BvaW50KGRhdGEgPSBzcGVjaWVzX3JlY2VpdmVyX3VzZVtzcGVjaWVzX3JlY2VpdmVyX3VzZSRzcGVjaWVzID09IHNwZWNpZXMsIF0sIAogICAgICAgICAgICAgICBtYXBwaW5nID0gYWVzKHggPSBsb24sIHkgPSBsYXQsIGNvbG9yID0gJ3JlZCcsIHNpemUgPSAgcmVjZWl2ZXJfdXNlKSkgKyAKICAgIGxhYnMoeCA9ICfCsExvbmdpdHVkZScsIHkgPSAnwrBMYXRpdHVkZScpICsKICAgIGdnc2F2ZShmaWxlbmFtZSA9IHBhc3RlKCdSZWNlaXZlciBVc2UgYnkgJywgc3BlY2llcywgJy5wZGYnLCBzZXAgPSAnJyksIHBhdGggPSBmaWd1cmVfZGlyZWN0b3J5KQogIHByaW50KHJlY2VpdmVyX3VzZV9ieV9zcHApCn0KYGBgCgojIyMgRGF5IE5pZ2h0IFBsb3RzCmBgYHtyfQojIyMgRGF5IE5pZ2h0IFBsb3RzCiMjIEZvciBhbGwgZmlzaApwZGYoZmlsZSA9IGZpbGUucGF0aChmaWd1cmVfZGlyZWN0b3J5LCAnRGF5IE5pZ2h0IFBsb3QgLSBBbGwgRmlzaC5wZGYnKSkKcGxvdF9kYXlfbmlnaHQobW9sb19kZiwgcGxvdF90aXRsZSA9ICdBbGwgRmlzaCcpCmRldi5vZmYoKQoKIyMgQnkgU3BlY2llcwpmb3IgKHNwcCBpbiB1bmlxdWUobW9sb19kZiRzcGVjaWVzKSl7CiAgcGRmKGZpbGUgPSBmaWxlLnBhdGgoZmlndXJlX2RpcmVjdG9yeSwgcGFzdGUoJ0RheSBOaWdodCBQbG90IC0gU3BlY2llcyAnLCBzcHAsICcucGRmJywgc2VwID0gJycpKSkKICBwbG90X2RheV9uaWdodChtb2xvX2RmW21vbG9fZGYkdGFnX2lkID09IG1vbG9fZGYkdGFnX2lkW21vbG9fZGYkc3BlY2llcyA9PSBzcHBdLCBdLCBwbG90X3RpdGxlID0gc3BwKQogIGRldi5vZmYoKQp9CgojIyBCeSBJbmRpdmlkdWFsCmZvciAodGFnX2lkIGluIHVuaXF1ZShtb2xvX2RmJHRhZ19pZCkpewogIHByaW50KHRhZ19pZCkKICAgIHBkZihmaWxlID0gZmlsZS5wYXRoKGZpZ3VyZV9kaXJlY3RvcnksIHBhc3RlKCdEYXkgTmlnaHQgUGxvdCAtIFRhZyBJRCAnLCB0YWdfaWQsICcucGRmJywgc2VwID0gJycpKSkKICBwbG90X2RheV9uaWdodChtb2xvX2RmW21vbG9fZGYkdGFnX2lkID09IHRhZ19pZCwgXSwgcGxvdF90aXRsZSA9IHBhc3RlKHRhZ2dpbmdfZGYkc3BlY2llc1t0YWdnaW5nX2RmJHRhZ19pZCA9PSB0YWdfaWRdLCAnLSBUYWcnLCBhcy5jaGFyYWN0ZXIodGFnX2lkKSwgc2VwID0gJyAnKSkKICBkZXYub2ZmKCkKfQpgYGAKCgojIyMgQmFycGxvdCBvZiBkZXRlY3Rpb25zIGJ5IGRhdGUKYGBge3J9CiMjIyBCYXIgcGxvdCBvZiBkZXRlY3Rpb25zIGluIGNyYXRlciBieSBkYXRlIApkZXRlY3Rpb25zX3Blcl9kYXlfZGYgPSBjb3VudF9kZXRlY3Rpb25zX3Blcl9kYXRlKG1vbG9fZGYpCgojIyBCYXJwbG90IG9mIGRldGVjdGlvbnMgYnkgaW5kaXZpZHVhbApmb3IoaSBpbiAxOm5yb3coZGV0ZWN0aW9uc19wZXJfZGF5X2RmKSl7CiAgIyMgQ29udmVydCBmcm9tIHdpZGUgdG8gbG9uZyBmb3JtYXQKICBpbmR2X2RhdGEgPSBtZWx0KGRldGVjdGlvbnNfcGVyX2RheV9kZltpLCBdKQogIGNvbG5hbWVzKGluZHZfZGF0YSkgPSBjKCdkYXRlJywgJ2RldGVjdGlvbnMnKQogIAogICMjIE1ha2UgYW5kIHNhdmUgcGxvdAogIGdncGxvdChkYXRhID0gaW5kdl9kYXRhLCBtYXBwaW5nID0gYWVzKHggPSBkYXRlLCB5ID0gZGV0ZWN0aW9ucykpICsKICAgIGdlb21fYmFyKHN0YXQgPSAiaWRlbnRpdHkiKSArIAogICAgbGFicyh0aXRsZSA9IHBhc3RlKCdUYWcgJywgcm93bmFtZXMoZGV0ZWN0aW9uc19wZXJfZGF5X2RmKVtpXSwgc2VwID0gJyAnKSwgeCA9ICdEYXRlJywgeSA9ICdEZXRlY3Rpb25zJykgKyAKICAgIGdnc2F2ZShmaWxlbmFtZSA9IHBhc3RlKCdEYWlseSBEZXRlY3Rpb24gQmFycGxvdCAtJywgcm93bmFtZXMoZGV0ZWN0aW9uc19wZXJfZGF5X2RmKVtpXSwgJy5wZGYnKSwgcGF0aCA9IGZpZ3VyZV9kaXJlY3RvcnkpCn0KCiMjIERldGVjdGlvbnMgYnkgc3BlY2llcwpkZXRlY3Rpb25zX3Blcl9kYXlfc3BwX3N0ZyA9IGRldGVjdGlvbnNfcGVyX2RheV9kZgpkZXRlY3Rpb25zX3Blcl9kYXlfc3BwX3N0ZyR0YWdfaWQgPSByb3duYW1lcyhkZXRlY3Rpb25zX3Blcl9kYXlfc3BwX3N0ZykKZGV0ZWN0aW9uc19wZXJfZGF5X3NwcF9zdGcgPSBsZWZ0X2pvaW4oeCA9IGRldGVjdGlvbnNfcGVyX2RheV9zcHBfc3RnLCB0YWdnaW5nX2RmWyAsYygndGFnX2lkJywgJ3NwZWNpZXMnKV0sIGJ5ID0gJ3RhZ19pZCcpCgojIyBMb29wIHRocm91Z2ggc3BlY2llcwpmb3IgKHNwcCBpbiB1bmlxdWUoZGV0ZWN0aW9uc19wZXJfZGF5X3NwcF9zdGckc3BlY2llcykpewogIAogICMjIFN1YnNldCBpbmRpdmlkdWFsIGRmIGJ5IHNwZWNpZXMKICBzcHBfc3Vic2V0X2RmID0gZGV0ZWN0aW9uc19wZXJfZGF5X3NwcF9zdGdbZGV0ZWN0aW9uc19wZXJfZGF5X3NwcF9zdGckc3BlY2llcyA9PSBzcHAsIC13aGljaChjb2xuYW1lcyhkZXRlY3Rpb25zX3Blcl9kYXlfc3BwX3N0ZykgJWluJSBjKCd0YWdfaWQnLCAnc3BlY2llcycpKV0KICAKICAjIyBDb252ZXJ0IHRvIGxvbmcgZm9ybWF0CiAgZGV0ZWN0aW9uc19wZXJfc3BwID0gbWVsdChjb2xTdW1zKHNwcF9zdWJzZXRfZGYpLCB2YWx1ZS5uYW1lID0gICAnZGV0ZWN0aW9ucycpCiAgZGV0ZWN0aW9uc19wZXJfc3BwJGRhdGUgPSByb3duYW1lcyhkZXRlY3Rpb25zX3Blcl9zcHApCiAgCiAgIyMgTWFrZSBhbmQgc2F2ZSBwbG90CiAgICBnZ3Bsb3QoZGF0YSA9IGRldGVjdGlvbnNfcGVyX3NwcCwgbWFwcGluZyA9IGFlcyh4ID0gZGF0ZSwgeSA9IGRldGVjdGlvbnMpKSArCiAgICBnZW9tX2JhcihzdGF0ID0gImlkZW50aXR5IikgKyAKICAgIGxhYnModGl0bGUgPSBzcHAsIHggPSAnRGF0ZScsIHkgPSAnRGV0ZWN0aW9ucycpICsgCiAgICBnZ3NhdmUoZmlsZW5hbWUgPSBwYXN0ZSgnRGFpbHkgRGV0ZWN0aW9uIEJhcnBsb3QgLScsIHNwcCwgJy5wZGYnKSwgcGF0aCA9IGZpZ3VyZV9kaXJlY3RvcnkpCn0KCiMjIEJhcnBsb3Qgb2YgYWxsIGRldGVjdGlvbnMKYWxsX2RldGVjdGlvbnMgPSBjb2xTdW1zKGRldGVjdGlvbnNfcGVyX2RheV9kZikKIyMgQ29udmVydCB0byBsb25nIGZvcm1hdAphbGxfZGV0ZWN0aW9uc19sb25nID0gbWVsdChhbGxfZGV0ZWN0aW9ucywgdmFsdWUubmFtZSA9ICAgJ2RldGVjdGlvbnMnKQphbGxfZGV0ZWN0aW9uc19sb25nJGRhdGUgPSByb3duYW1lcyhhbGxfZGV0ZWN0aW9uc19sb25nKQogIAojIyBNYWtlIGFuZCBzYXZlIHBsb3QKZ2dwbG90KGRhdGEgPSBhbGxfZGV0ZWN0aW9uc19sb25nLCBtYXBwaW5nID0gYWVzKHggPSBkYXRlLCB5ID0gZGV0ZWN0aW9ucykpICsKZ2VvbV9iYXIoc3RhdCA9ICJpZGVudGl0eSIpICsgCmxhYnModGl0bGUgPSAnQWxsIFRhZ2dlZCBJbmRpdmlkdWFscycsIHggPSAnRGF0ZScsIHkgPSAnRGV0ZWN0aW9ucycpICsgCmdnc2F2ZShmaWxlbmFtZSA9IHBhc3RlKCdEYWlseSBEZXRlY3Rpb24gQmFycGxvdCAtIGFsbCB0YWdzLnBkZicpLCBwYXRoID0gZmlndXJlX2RpcmVjdG9yeSkKYGBgCgojIyMgQmFyIHBsb3QgIyBvZiBGaXNoIChzdGFuZGFyZGl6ZWQgcGVyY2VudCBvZiBmaXNoIHRhZ2dlZCB0byBkYXRlKSBieSBkYXRlIGFuZCBTcHAKCgpUSElTIE5FRURTIFdPUkshISEKYGBge3J9CiMjIENvbnZlcnQgZGV0ZWN0aW9uc19wZXJfZGF5IHRvIHByZXNlbmNlL2Fic2VuY2UKcHJlc2VuY2VfYWJzZW5jZV93aWRlX2RmID0gZGV0ZWN0aW9uc19wZXJfZGF5X2RmCnByZXNlbmNlX2Fic2VuY2Vfd2lkZV9kZltwcmVzZW5jZV9hYnNlbmNlX3dpZGVfZGYgPiAwXSA9IDEKCiMjIENvbnZlcnQgZnJvbSB3aWRlIHRvIGxvbmcgZm9ybWF0CnByZXNlbmNlX2Fic2VuY2VfbG9uZ19kZiA9IG1lbHQocHJlc2VuY2VfYWJzZW5jZV93aWRlX2RmLCBpZC52YXJzID0gYygnZGF0ZScpLCBtZWFzdXJlLnZhcnMgPSBjb2xuYW1lcyhwcmVzZW5jZV9hYnNlbmNlX3dpZGVfZGYpWzI6bmNvbChwcmVzZW5jZV9hYnNlbmNlX3dpZGVfZGYpXSwgdmFyaWFibGUubmFtZSA9ICd0YWdfaWQnLCB2YWx1ZS5uYW1lID0gJ2RldGVjdGVkJykKCiMgRHJvcCAndGFnXycgcHJlZml4IGZyb20gdGFnX2lkIGNvbHVtbiBmb3IgbWF0Y2hpbmcgcHVycG9zZXMKcHJlc2VuY2VfYWJzZW5jZV9sb25nX2RmJHRhZ19pZCA9IGxldmVscyhwcmVzZW5jZV9hYnNlbmNlX2xvbmdfZGYkdGFnX2lkKVtwcmVzZW5jZV9hYnNlbmNlX2xvbmdfZGYkdGFnX2lkXQpmb3IoaSBpbiAxOm5yb3cocHJlc2VuY2VfYWJzZW5jZV9sb25nX2RmKSl7CiAgcHJlc2VuY2VfYWJzZW5jZV9sb25nX2RmJHRhZ19pZFtpXSA9IHN0cnNwbGl0KHByZXNlbmNlX2Fic2VuY2VfbG9uZ19kZiR0YWdfaWRbaV0sIHNwbGl0ID0gJ18nKVtbMV1dWzJdCn0KCiMjIE1lcmdlIHdpdGggc3BlY2llcyBmcm9tIHRhZ2dpbmcgZGF0YQpwcmVzZW5jZV9hYnNlbmNlX2xvbmdfZGYgPSBtZXJnZSh4ID0gcHJlc2VuY2VfYWJzZW5jZV9sb25nX2RmLCB5ID0gdGFnZ2luZ19kZlsgLGMoJ3RhZ19pZCcsICdzcGVjaWVzJyldLCBvbiA9ICd0YWdfaWQnKQoKIyMgRHJvcCBkYXRlIGFuZCB0YWcgcGFpcnMgcHJlY2VkaW5nIHRoZSBkYXRlIHRoZSBmaXNoIHdhcyB0YWdnZWQKaW5kaWNpZXNfdG9fZHJvcCA9IGMoKQpmb3IoaSBpbiBucm93KHByZXNlbmNlX2Fic2VuY2VfbG9uZ19kZikpewogIGlmKGFzLkRhdGUodGFnZ2luZ19kZiRkYXRldGltZVt0YWdnaW5nX2RmJHRhZ19pZCA9PSBwcmVzZW5jZV9hYnNlbmNlX2xvbmdfZGYkdGFnX2lkW2ldXSkgPD0gcHJlc2VuY2VfYWJzZW5jZV9sb25nX2RmJGRhdGVbaV0pewogICAgaW5kaWNpZXNfdG9fZHJvcCA9IGMoaW5kaWNpZXNfdG9fZHJvcCwgaSkKICB9Cn0KcHJlc2VuY2VfYWJzZW5jZV9sb25nX2RmID0gcHJlc2VuY2VfYWJzZW5jZV9sb25nX2RmWy1pbmRpY2llc190b19kcm9wLCBdCgojIyBHZXQgYSBsaXN0IG9mIGFjdGl2ZSB0YWdzIGJ5IGRhdGUgYW5kIHNwZWNpZXMKYWN0aXZlX3RhZ3NfYnlfZGF0ZSA9IGFnZ3JlZ2F0ZSh0YWdfaWQgfiBkYXRlICsgc3BlY2llcywgZGF0YSA9IHByZXNlbmNlX2Fic2VuY2VfbG9uZ19kZiwgRlVOID0gdW5pcXVlTikKICBjb2xuYW1lcyhhY3RpdmVfdGFnc19ieV9kYXRlKSA9IGMoJ2RhdGUnLCAnc3BlY2llcycsICdkZXBsb3llZF90YWdzJykKCiMjIFN0YW5kYXJkaXplIHRhZyBjb3VudHMgYnkgdGFncyBkZXBsb3llZCBhbmQgcGxvdCBhcyAlIG9mIHRhZ3MgZGV0ZWN0ZWQgcGVyIGRheSBieSBzcGVjaWVzCmZvcihzcGVjaWVzIGluIHVuaXF1ZShwcmVzZW5jZV9hYnNlbmNlX2xvbmdfZGYkc3BlY2llcykpewogIAogICMgQ291bnQgbnVtYmVyIG9mIHRhZ3MgZGV0ZWN0ZWQgZGFpbHkgYnkgc3BlY2llcyAKICBwcmVzZW5jZV9hYnNlbmNlX2J5X3NwcF9kZiA9IGFnZ3JlZ2F0ZShkZXRlY3RlZH5kYXRlLCBkYXRhID0gcHJlc2VuY2VfYWJzZW5jZV9sb25nX2RmW3ByZXNlbmNlX2Fic2VuY2VfbG9uZ19kZiRzcGVjaWVzID09IHNwZWNpZXMsIF0sIEZVTiA9IHN1bSkKICBjb2xuYW1lcyhwcmVzZW5jZV9hYnNlbmNlX2J5X3NwcF9kZikgPSBjKCdkYXRlJywgJ3RhZ3NfZGV0ZWN0ZWQnKQogIAogICMgU3RhbmRhcmRpemUgZGFpbHkgdGFnIGNvdW50IGJ5IHRoZSBudW1iZXIgb2YgdGFncyBkZXBsb3llZAogIHByZXNlbmNlX2Fic2VuY2VfYnlfc3BwX2RmID0gbWVyZ2UoeCA9IHByZXNlbmNlX2Fic2VuY2VfYnlfc3BwX2RmLCB5ID0gYWN0aXZlX3RhZ3NfYnlfZGF0ZVthY3RpdmVfdGFnc19ieV9kYXRlJHNwZWNpZXMgPT0gc3BlY2llcywgXSwgb24gPSAnZGF0ZScpCiAgcHJlc2VuY2VfYWJzZW5jZV9ieV9zcHBfZGYkcGVyY2VudF90YWdzX2RldGVjdGVkID0gcHJlc2VuY2VfYWJzZW5jZV9ieV9zcHBfZGYkZGV0ZWN0ZWQgLyBwcmVzZW5jZV9hYnNlbmNlX2J5X3NwcF9kZiRkZXBsb3llZF90YWdzCiAgCiAgIyBNYWtlIHBsb3QgYXQgc3BlY2llcyBsZXZlbAogIGdncGxvdChkYXRhID0gcHJlc2VuY2VfYWJzZW5jZV9ieV9zcHBfZGYsIG1hcHBpbmcgPSBhZXMoeCA9IGRhdGUsIHkgPSBwZXJjZW50X3RhZ3NfZGV0ZWN0ZWQpKSArIAogICAgZ2VvbV9iYXIoc3RhdCA9ICdpZGVudGl0eScpICsgCiAgICBsYWJzKHRpdGxlID0gc3BlY2llcywgeCA9ICdEYXRlJywgeSA9ICclIG9mIHRhZ3MgZGV0ZWN0ZWQnKSArCiAgICBnZ3NhdmUoZmlsZW5hbWUgPSBwYXN0ZSgnRGV0ZWN0aW9ucyBTdGFuZGFyZGl6ZWQgQnkgU3BlY2llcyAtICcsIHNwZWNpZXMsICcucGRmJywgc2VwID0gJycpLCBwYXRoID0gZmlndXJlX2RpcmVjdG9yeSkKfQoKYGBgCgojIyMgQmFyIHBsb3QgdmVzc2VsIHRyYWZmaWMgYnkgZGF0ZQpJbiB0aGUgZnV0dXJlLCBtaWdodCBhbHNvIGNvbnNpZGVyIG1heCB2ZXNzZWxzIHByZXNlbnQgYXQgYSBnaXZlbiB0aW1lCmBgYHtyfQoKIyMgQ2FsY3VsYXRlIERhaWx5IFZlc3NlbCBTdGF0cwp2ZXNzZWxzX3Blcl9kYXkgPSBhZ2dyZWdhdGUodmVzc2VsX25hbWUgfiBEYXRlKGRhdGUpLCBkYXRhID0gdmVzc2VsX2RmLCBGVU4gPSB1bmlxdWVOKQpjb2xuYW1lcyh2ZXNzZWxzX3Blcl9kYXkpID0gYygnZGF0ZScsICd0b3RhbF92ZXNzZWxzJykKCgoKIyBNYWtlIHBsb3QgZm9yIHRvdGFsIAp0b3RhbF92ZXNzZWxzX3Bsb3QgPSBnZ3Bsb3QoZGF0YSA9IHZlc3NlbHNfcGVyX2RheSwgbWFwcGluZyA9IGFlcyh4ID0gZGF0ZSwgeSA9IHRvdGFsX3Zlc3NlbHMpKSArIAogICAgZ2VvbV9iYXIoc3RhdCA9ICdpZGVudGl0eScpICsgCiAgICBsYWJzKHRpdGxlID0gJ01heGltdW0gTnVtYmVyIG9mIENvLW9jY3VyaW5nIFZlc3NlbHMgRGFpbHknLCB4ID0gJ0RhdGUnLCB5ID0gJyMgb2YgVmVzc2VscycpICsKICAgIGdnc2F2ZShmaWxlbmFtZSA9IHBhc3RlKCdUb3RhbCBWZXNzZWxzIERhaWx5LnBkZiAnLCBzcGVjaWVzLCAnLnBkZicsIHNlcCA9ICcnKSwgcGF0aCA9IGZpZ3VyZV9kaXJlY3RvcnkpCgpwcmludChtYXhfdmVzc2Vsc19wbG90KQpwcmludCh0b3RhbF92ZXNzZWxzX3Bsb3QpCmBgYAoKCiMjIyBTY2F0dGVyIHBsb3QgeCBheGlzIGJvYXQgdHJhZmZpYywgeSBheGlzIHByZXNlbmNlIC8gYWJzZW5jZSBjb2xvciBieSBzcHAKYGBge3J9CgpgYGAKCiMjIyBTY2F0dGVyIHBsb3QgeCBheGlzIGJvYXQgdHJhZmZpYywgeSBheGlzIGRldGVjdGlvbnMgcGVyIGluZGl2aWR1YWwgY29sb3IgYnkgc3BwIGFkZCBlcnJvciBiYXJzIGZvciBkYWlseSBkZXRlY3Rpb25zCmBgYHtyfQoKYGBgCgojIFJlc2lkZW5jeSBhbmQgZGlzcGVyc2FsCmBgYHtyfQojIyBDYWxjdWxhdGUgcmVzaWRlbmN5CmRldGVjdGlvbl9zdGF0cyRyZXNpZGVuY2VfbWV0cmljID0gZGV0ZWN0aW9uX3N0YXRzJHVuaXF1ZV9kYXlzIC8gZGV0ZWN0aW9uX3N0YXRzJGRheXNfYXRfbGliZXJ0eQoKIyMgQXNzaWduIHJlc2lkZW5jZSBjYXRlZ29yeTogbG93ID0gPCAzMyUsIG1lZGl1bSA9IDMzIC0gNjYsIGhpZ2ggPSA+PSA2NiAoVGluaGFuIGV0IGFsLiAyMDE0KSAtCmRldGVjdGlvbl9zdGF0cyRyZXNpZGVuY2VfY2F0ZWdvcnkgPSAnTG93Jwpmb3IgKGkgaW4gMTpucm93KGRldGVjdGlvbl9zdGF0cykpewogIGlmIChkZXRlY3Rpb25fc3RhdHMkcmVzaWRlbmNlX21ldHJpY1tpXSA+PSAoMS8zKSkgewogICAgZGV0ZWN0aW9uX3N0YXRzJHJlc2lkZW5jZV9jYXRlZ29yeVtpXSA9ICdNZWRpdW0nCiAgfQogIGlmIChkZXRlY3Rpb25fc3RhdHMkcmVzaWRlbmNlX21ldHJpY1tpXSA+PSAoMi8zKSkgewogICAgZGV0ZWN0aW9uX3N0YXRzJHJlc2lkZW5jZV9jYXRlZ29yeVtpXSA9ICdIaWdoJwogIH0KfQoKIyMgQ3JlYXRlIGdyb3VwZWQgYmFycGxvdCBvZiByZXNpZGVuY3kgYnkgc3BlY2llcwpyZXNpZGVuY2VfY291bnRzX2J5X3NwZWNpZXMgPSBhZ2dyZWdhdGUodGFnX2lkIH4gc3BlY2llcyArIHJlc2lkZW5jZV9jYXRlZ29yeSwgZGF0YSA9IGRldGVjdGlvbl9zdGF0cywgRlVOID0gbGVuZ3RoKQoKZ2dwbG90KGRhdGEgPSByZXNpZGVuY2VfY291bnRzX2J5X3NwZWNpZXMsIG1hcHBpbmcgPSBhZXMoeD1zcGVjaWVzLCB5PXRhZ19pZCwgZmlsbD1yZXNpZGVuY2VfY2F0ZWdvcnkpKSArCiAgZ2VvbV9iYXIoc3RhdD0iaWRlbnRpdHkiLCBwb3NpdGlvbiA9ICJkb2RnZSIpCmBgYAoKVGFrZWF3YXlzIC0gQWxsIDQgb21pbHVzIHdlcmUgaGlnaGx5IHJlc2lkZW50IGFzIHdlcmUgZ3JleSByZWVmIHNoYXJrcy4gTm8gb3RoZXIgc3BlY2llcyBoYXZlIHJlcGxpY2F0ZXMgc28uLi4/CgojIyBDYWxjdWxhdGUgMzAgZGF5IG1vdmluZyBhdmVyYWdlIG9mIHJlc2lkZW5jeSwgdGhlbiBwbG90IGFnYWluc3QgZGF5cyBzaW5jZSB0YWdnaW5nCmBgYHtyfQojIyBHZXQgdG90YWwgZGF5cyBpbiB0aGUgc3R1ZHkKdG90YWxfZGF5c19pbl9zdHVkeSA9IGFzLm51bWVyaWMoZGlmZi5EYXRlKGMobWluKG1vbG9fZGYkZGF0ZSksIG1heChtb2xvX2RmJGRhdGUpKSkpCgojIyBDcmVhdGUgYSBkYXRhZnJhbWUgd2hlcmUgcm93cyBhcmUgdGFnIGlkIGFuZCBjb2x1bW5zIGFyZSBzdHVkeSBkYXRlCnByZXNlbnRfYWZ0ZXJfbl9kYXlzX2RmID0gZGF0YS5mcmFtZSgpCgojIyBEZXRlcm1pbmUgaWYgYSB0YWcgd2FzIGRldGVjdGVkIG9uIGEgcmVjZWl2ZXIgbiBkYXlzIGFmdGVyIHRhZ2dpbmcKZm9yIChpIGluIDE6dW5pcXVlTihtb2xvX2RmJHRhZ19pZCkpewogICMjIFN1YnNldCBkYXRhIGZvciBpbmRpdmlkdWFsIHRhZ3MKICBpbmR2X2RhdGEgPSBtb2xvX2RmW21vbG9fZGYkdGFnX2lkID09IHVuaXF1ZShtb2xvX2RmJHRhZ19pZClbaV0sIF0KICAjIyBEZXRlcm1pbmUgaWYgYSBmaXNoIHdhcyBwcmVzZW50IG4gZGF5cyBhZnRlciB0YWdnaW5nCiAgZGlmZnRpbWVzID0gcmVwKDAsIGxlbiA9IHRvdGFsX2RheXNfaW5fc3R1ZHkpCiAgIyBkZXRlcm1pbmUgZGlmZmVyZW5jZSBpbiBkYXlzIGJldHdlZW4gZWFjaCB1bmlxdWUgZGF5IGEgdGFnIHdhcyBkZXRlY3RlZCBhbmQgdGhlIHRhZydzIGVhcmxpZXN0IGRldGVjdGlvbiwgZmxpcCB0aGUgY29ycmVzcG9uZGluZyB2YWx1ZSBpbiBkaWZmdGltZXMgYXJyYXkgdG8gMQogIGRldGVjdGVkX2RhdGVzID0gdW5pcXVlKGluZHZfZGF0YSRkYXRlKQogIGZvciAoaiBpbiAxOmxlbmd0aChkZXRlY3RlZF9kYXRlcykpewogICAgZGlmZnRpbWVzW2FzLm51bWVyaWMoZGlmZi5EYXRlKGMobWluKGluZHZfZGF0YSRkYXRlKSwgZGV0ZWN0ZWRfZGF0ZXNbal0pKSkgKyAxXSA9IDEKICB9CiAgZGZfcm93ID0gYyh1bmlxdWUobW9sb19kZiR0YWdfaWQpW2ldLCBkaWZmdGltZXMpCiAgcHJlc2VudF9hZnRlcl9uX2RheXNfZGYgPSByYmluZChwcmVzZW50X2FmdGVyX25fZGF5c19kZiwgZGZfcm93KQp9CmNvbG5hbWVzKHByZXNlbnRfYWZ0ZXJfbl9kYXlzX2RmKSA9IGMoJ3RhZ19pZCcsIGFzLmNoYXJhY3RlcigxOnRvdGFsX2RheXNfaW5fc3R1ZHkpKQoKIyMgQ29udmVydCBmcm9tIHdpZGUgZm9ybWF0IHRvIGxvbmcgZm9ybWF0CnByZXNlbnRfYWZ0ZXJfbl9kYXlzX2RmX2xvbmdfZGYgPSBtZWx0KHByZXNlbnRfYWZ0ZXJfbl9kYXlzX2RmLCBpZC52YXJzID0gJ3RhZ19pZCcsIG1lYXN1cmUudmFycyA9IGNvbG5hbWVzKHByZXNlbnRfYWZ0ZXJfbl9kYXlzX2RmKVsyOm5jb2wocHJlc2VudF9hZnRlcl9uX2RheXNfZGYpXSwgdmFyaWFibGUubmFtZSA9ICdkYXknLCB2YWx1ZS5uYW1lID0gJ2RldGVjdGVkJykKCiMjIE1lcmdlIHdpdGggc3BlY2llcyBkYXRhCnByZXNlbnRfYWZ0ZXJfbl9kYXlzX2RmX2xvbmdfZGYgPSBsZWZ0X2pvaW4oeCA9IHByZXNlbnRfYWZ0ZXJfbl9kYXlzX2RmX2xvbmdfZGYsIHkgPSB0YWdnaW5nX2RmWyAsYygndGFnX2lkJywgJ3NwZWNpZXMnKV0sIGJ5ID0gJ3RhZ19pZCcpCiMgUmVjYXN0IHRvIG51bWVyaWMgYmVjYXVzZSBvZiB0aGUgam9pbiBmdW5jdGlvbgpwcmVzZW50X2FmdGVyX25fZGF5c19kZl9sb25nX2RmJGRldGVjdGVkID0gYXMubnVtZXJpYyhwcmVzZW50X2FmdGVyX25fZGF5c19kZl9sb25nX2RmJGRldGVjdGVkKQoKIyMgQ2FsY3VsYXRlIG51bWJlciBvZiBlYWNoIHNwZWNpZXMgcHJlc2VudCBuIGRheXMgYWZ0ZXIgdGFnZ2luZwpzcGVjaWVzX3ByZXNlbmNlX2FmdGVyX3RhZ2dpbmcgPSBhZ2dyZWdhdGUoZGV0ZWN0ZWQgfiBzcGVjaWVzICsgZGF5LCBkYXRhID0gcHJlc2VudF9hZnRlcl9uX2RheXNfZGZfbG9uZ19kZiwgRlVOID0gc3VtKQogIGNvbG5hbWVzKHNwZWNpZXNfcHJlc2VuY2VfYWZ0ZXJfdGFnZ2luZykgPSBjKCdzcGVjaWVzJywgJ2RheScsICduX2RldGVjdGVkJykKCiMjIENvdW50IHVuaXF1ZSB0YWdzIGJ5IHNwZWNpZXMKaW5kaXZpZHVhbHNfcGVyX3NwZWNpZXMgPSBhZ2dyZWdhdGUodGFnX2lkIH4gc3BlY2llcywgZGF0YSA9IHByZXNlbnRfYWZ0ZXJfbl9kYXlzX2RmX2xvbmdfZGYsIEZVTiA9IHVuaXF1ZU4pCmNvbG5hbWVzKGluZGl2aWR1YWxzX3Blcl9zcGVjaWVzKSA9IGMoJ3NwZWNpZXMnLCAnbl90YWdnZWQnKQoKIyMgU3RhbmRhcmRpemUgc3BlY2llcyBsZXZlbCBkYWlseSBjb3VudHMgYnkgbnVtYmVyIG9mIHRhZ3MgYmVsb25naW5nIHRvIHRoYXQgc3BlY2llcwpzcGVjaWVzX3ByZXNlbmNlX2FmdGVyX3RhZ2dpbmcgPSBsZWZ0X2pvaW4oeCA9IHNwZWNpZXNfcHJlc2VuY2VfYWZ0ZXJfdGFnZ2luZywgeSA9IGluZGl2aWR1YWxzX3Blcl9zcGVjaWVzLCBieSA9ICdzcGVjaWVzJykKc3BlY2llc19wcmVzZW5jZV9hZnRlcl90YWdnaW5nJHBlcmNlbnRfaW5kaXZpZHVhbHNfZGV0ZWN0ZWQgPSBzcGVjaWVzX3ByZXNlbmNlX2FmdGVyX3RhZ2dpbmckbl9kZXRlY3RlZCAvIHNwZWNpZXNfcHJlc2VuY2VfYWZ0ZXJfdGFnZ2luZyRuX3RhZ2dlZAoKIyMgQ29udmVydCBkYXkgZnJvbSBmYWN0b3IgdG8gbnVtZXJpYwpzcGVjaWVzX3ByZXNlbmNlX2FmdGVyX3RhZ2dpbmckZGF5ID0gYXMubnVtZXJpYyhsZXZlbHMoc3BlY2llc19wcmVzZW5jZV9hZnRlcl90YWdnaW5nJGRheSlbc3BlY2llc19wcmVzZW5jZV9hZnRlcl90YWdnaW5nJGRheV0pCgojIyByZW1vdmUgYW55IE5BIGRheXMKc3BlY2llc19wcmVzZW5jZV9hZnRlcl90YWdnaW5nID0gc3BlY2llc19wcmVzZW5jZV9hZnRlcl90YWdnaW5nWyFpcy5uYShzcGVjaWVzX3ByZXNlbmNlX2FmdGVyX3RhZ2dpbmckZGF5KSwgXQoKIyMgQ2FsY3VsYXRlIDMwIGRheSBtb3ZpbmcgYXZlcmFnZQpzcHBfcHJlc2VuY2VfMzBfZGF5X2F2ZyA9IGRhdGEuZnJhbWUoKQpmb3IgKHNwZWNpZXMgaW4gdW5pcXVlKHNwZWNpZXNfcHJlc2VuY2VfYWZ0ZXJfdGFnZ2luZyRzcGVjaWVzKSl7CiAgc3BwX3ByZXNlbmNlX2FmdGVyX3RhZ2dpbmcgPSBzcGVjaWVzX3ByZXNlbmNlX2FmdGVyX3RhZ2dpbmdbc3BlY2llc19wcmVzZW5jZV9hZnRlcl90YWdnaW5nJHNwZWNpZXMgPT0gc3BlY2llcywgXQogIG1vdmluZ19hdmVyYWdlXzMwID0gYygpCiAgZm9yIChpIGluIDMwOm1heChzcHBfcHJlc2VuY2VfYWZ0ZXJfdGFnZ2luZyRkYXkpKXsKICAgIG1vdmluZ19hdmVyYWdlXzMwID0gYyhtb3ZpbmdfYXZlcmFnZV8zMCwgbWVhbihzcHBfcHJlc2VuY2VfYWZ0ZXJfdGFnZ2luZyRwZXJjZW50X2luZGl2aWR1YWxzX2RldGVjdGVkW3NwcF9wcmVzZW5jZV9hZnRlcl90YWdnaW5nJGRheSA+PSBpLTMwICYgc3BwX3ByZXNlbmNlX2FmdGVyX3RhZ2dpbmckZGF5IDw9IGldKSkKICB9CiAgZGZfcm93ID0gYyhzcGVjaWVzLCBtb3ZpbmdfYXZlcmFnZV8zMCkKICBzcHBfcHJlc2VuY2VfMzBfZGF5X2F2ZyA9IHJiaW5kKHNwcF9wcmVzZW5jZV8zMF9kYXlfYXZnLCBkZl9yb3cpCn0KY29sbmFtZXMoc3BwX3ByZXNlbmNlXzMwX2RheV9hdmcpID0gYygnc3BlY2llcycsIGFzLmNoYXJhY3RlcigxOihuY29sKHNwcF9wcmVzZW5jZV8zMF9kYXlfYXZnKS0xKSkpCgojIyBDb252ZXJ0IGZyb20gd2lkZSBmb3JtYXQgdG8gbG9uZyBmb3JtYXQKc3BwX3ByZXNlbmNlXzMwX2RheV9hdmdfbG9uZ19kZiA9IG1lbHQoc3BwX3ByZXNlbmNlXzMwX2RheV9hdmcsIGlkLnZhcnMgPSAnc3BlY2llcycsIG1lYXN1cmUudmFycyA9IGNvbG5hbWVzKHNwcF9wcmVzZW5jZV8zMF9kYXlfYXZnKVsyOm5jb2woc3BwX3ByZXNlbmNlXzMwX2RheV9hdmcpXSwgdmFyaWFibGUubmFtZSA9ICdkYXknLCB2YWx1ZS5uYW1lID0gJ3BlcmNlbnRfaW5kaXZpZHVhbHNfZGV0ZWN0ZWQnKQoKIyBDb252ZXJ0IHBlcmNlbnRfaW5kaXZpZHVhbHNfZGV0ZWN0ZWQgYW5kIGRhdGUKc3BwX3ByZXNlbmNlXzMwX2RheV9hdmdfbG9uZ19kZiRwZXJjZW50X2luZGl2aWR1YWxzX2RldGVjdGVkID0gYXMubnVtZXJpYyhzcHBfcHJlc2VuY2VfMzBfZGF5X2F2Z19sb25nX2RmJHBlcmNlbnRfaW5kaXZpZHVhbHNfZGV0ZWN0ZWQpCgpzcHBfcHJlc2VuY2VfMzBfZGF5X2F2Z19sb25nX2RmJGRheSA9IGFzLm51bWVyaWMobGV2ZWxzKHNwcF9wcmVzZW5jZV8zMF9kYXlfYXZnX2xvbmdfZGYkZGF5KVtzcHBfcHJlc2VuY2VfMzBfZGF5X2F2Z19sb25nX2RmJGRheV0pCgoKIyMgR2VuZXJhdGUgbGluZSBwbG90CnByZXNlbnRfYWZ0ZXJfdGFnZ2luZ19wbG90ID0gZ2dwbG90KHNwcF9wcmVzZW5jZV8zMF9kYXlfYXZnX2xvbmdfZGYsIG1hcHBpbmcgPSBhZXMoeCA9IGRheSwgeSA9IHBlcmNlbnRfaW5kaXZpZHVhbHNfZGV0ZWN0ZWQsIGNvbG9yID0gc3BlY2llcykpICsgCiAgZ2VvbV9saW5lKCkgKyAKICBsYWJzKHggPSAnTnVtYmVyIG9mIGRheXMnLCB5ID0gJ1Byb3BvcnRpb24gcHJlc2VudCcpICsKICBnZ3NhdmUoZmlsZW5hbWUgPSAnUHJvcG9ydGlvbiBvZiB0YWdzIHByZXNlbnQgYWZ0ZXIgdGFnZ2luZy5wZGYnLCBwYXRoID0gZmlndXJlX2RpcmVjdG9yeSkKCnByaW50KHByZXNlbnRfYWZ0ZXJfdGFnZ2luZ19wbG90KQpgYGAKCiMgU3RhdGlzdGljYWwgYW5hbHlzaXMKCkNhbGN1bGF0ZSBtZWFuIHJlc2lkZW5jeSBieSBzcHAgKGlycmVnYXJkbGVzcyBvZiB0aW1lKSwgdGhlbiBBTk9WQSBieSBzcHAKVXNlIFR1a2V5J3MgSFNEIHRvIGRldGVybWluZSBzaWduaWZpY2FuY2UKYGBge3J9CiMjIEFOT1ZBIG1vZGVsIGZvciByZXNpZGVuY3kgbWV0cmljIGJ5IHNwZWNpZXMKcmVzaWRlbmNlX2J5X3NwZWNpZXNfYW5vdmEgPSBhb3YocmVzaWRlbmNlX21ldHJpYyB+IHNwZWNpZXMsIGRhdGE9ZGV0ZWN0aW9uX3N0YXRzKQpzdW1tYXJ5KHJlc2lkZW5jZV9ieV9zcGVjaWVzX2Fub3ZhKQoKIyMgVHVrZXkncyBIb25lc3RseSBTaWduaWZpY2FudCBEaWZmZXJlbmNlcyBiZXR3ZWVuIHNwZWNpZXMKVHVrZXlIU0QocmVzaWRlbmNlX2J5X3NwZWNpZXNfYW5vdmEpCmBgYAoKR0xNIGNvbXBhcmluZyByZXNpZGVuY3kgdGltZSBieSBzcHAgaW5kZXBlbmRlbnQgdmFyICh0aW1lIGF0IGxpYmVydHkpIGRlcGVuZGVudCAocmVzaWRlbmN5IGluZGV4KQpgYGB7cn0KIyMgRml0IGJpbm9taWFsIEdMTSB0byBhdmVyYWdlIHJlc2lkZW5jeSBtZXRyaWMgZGF0YSAocHJvcG9ydGlvbmFsIGJldHdlZW4gMC0xKQpzcGVjaWVzX2dsbSA9IGdsbShyZXNpZGVuY2VfbWV0cmljIH4gIHNwZWNpZXMgKiBkYXlzX2F0X2xpYmVydHksIGRhdGEgPSBkZXRlY3Rpb25fc3RhdHMsIGZhbWlseSA9IGJpbm9taWFsKGxvZ2l0KSkKc3VtbWFyeShzcGVjaWVzX2dsbSkKYGBgCk5vIFNpZ25pZmljYW50IGRpZmZlcmVuY2VzIGZvdW5kIAoKCiMjIEdMTSBjb21wYXJpbmcgdGltZSBpbiBjcmF0ZXIgdG8gdmVzc2VsIHRyYWZmaWMKYGBge3J9CgpgYGA=